<template>
    <div
        class="lk-tree-node"
        @click.stop="handleClick"
        @contextmenu="($event)=>this.handleContextMenu($event)"
        v-show="node.visible"
        :class="{
            'is-expanded':expanded,
            'is-current':node.isCurrent,
            'is-hidden':!node.visible,
            'is-focusable':!node.disabled,
            'is-checked':!node.disabled&&node.checked
        }"
        role="treeitem"
        tabindex="-1"
        :aria-expanded="expanded"
        :aria-disabled="node.disabled"
        :aria-checked="node.checked"
        :draggable="tree.draggable"
        @dragstart.stop="handleDragStart"
        @dragover.stop="handleDragOver"
        @dragend.stop="handleDragEnd"
        @drop.stop="handleDrop"
        ref="node">
        <div class="lk-tree-node__content"
            :style="{'padding-left':(node.level-1)*tree.indent+'px'}">
            <span
                @click.stop="handleExpandIconClick"
                :class="[
                    {'is-leaf':node.isLeaf,'expanded':!node.isLeaf&&expanded},
                    'lk-tree-node__expand-icon',
                    tree.iconClass?tree.iconClass:'el-icon-caret-right'
                ]"
            >
            </span>
            <i :class="[
                {'el-icon-folder':node.data.isfold,
                'el-icon-document':!node.data.isfold},
                'lk-tree-node__isfold-icon'
            ]"></i>
            <el-checkbox
                v-if="showCheckbox"
                v-model="node.checked"
                :indeterminate="node.indeterminate"
                :disabled="!!node.disabled"
                @click.native.stop
                @change="handleCheckChange"
            >
            </el-checkbox>
            <span
                v-if="node.loading"
                class="lk-tree-node__loading-icon el-icon-loading">
            </span>
            <node-content :node="node"></node-content>
        </div>
        <el-collapse-transition>
            <div
                class="lk-tree-node__children"
                v-if="!renderAfterExpand||childNodeRendered"
                v-show="expanded"
                role="group"
                :aria-expanded="expanded"
            >
                <lk-tree-node
                 :render-content="renderContent"
                 v-for="child in node.childNodes"
                 :render-after-expand="renderAfterExpand"
                 :show-checkbox="showCheckbox"
                 :key="getNodeKey(child)"
                 :node="child"
                 @node-expand="handleChildNodeExpand">
                </lk-tree-node>
            </div>
        </el-collapse-transition>
    </div>
</template>
<script type="text/jsx">
import emitter from 'common/js/mixins/emitter'
import { getNodeKey } from './model/util'
export default {
    name:'LkTreeNode',
    componentName:'LkTreeNode',
    mixins:[emitter],
    props:{
        node:{
            default(){
                return {}
            }
        },
        props:{},
        renderContent:Function,
        renderAfterExpand:{
            type:Boolean,
            default:true
        },
        showCheckbox:{
            type:Boolean,
            default:false
        }
    },
    components:{
        NodeContent:{
            props:{
                node:{
                    required:true
                }
            },
            render(h){
                const parent=this.$parent
                const tree=parent.tree
                const node=this.node
                const {data,store}=node
                return (
                    parent.renderContent
                    ?parent.renderContent.call(parent._renderProxy,h,
                    {_self:tree.$vnode.context,node,data,store})
                    :tree.$scopedSlots.default
                    ?tree.$scopedSlots.default({node,data})
                    :<span class="lk-tree-node__label">{node.label}</span>
                )
            }
        }
    },
    data()
    {
        return {
            tree:null,
            expanded:false,
            childNodeRendered:false,
            oldChecked:null,
            oldIndeterminate:null
        }
    },
    watch:{
        'node.indeterminate'(val){
            this.handleSelectChange(this.node.checked,val)
        },
        'node.checked'(val){
            this.handleSelectChange(val,this.node.indeterminate)
        },
        'node.expanded'(val)
        {
            this.$nextTick(()=>this.expanded=val)
            if(val)
            {
                this.childNodeRendered=true
            }
        }
    },
    methods:{
        getNodeKey(node)
        {
            return getNodeKey(this.tree.nodeKey,node.data)
        },
        handleSelectChange(checked,indeterminate)
        {
            if(this.oldChecked!==checked&&this.oldIndeterminate!==indeterminate)
            {
                this.tree.$emit('check-change',this.node.data,checked,indeterminate)
            }
            this.oldIndeterminate=checked
            this.indeterminate=indeterminate
        },
        handleClick(){
            const store=this.tree.store
            store.setCurrentNode(this.node)
            this.tree.$emit('current-change',store.currentNode?store.currentNode.data:null,store.currentNode)
            this.tree.currentNode=this
            if(this.tree.expandOnClickNode)
            {
                this.handleExpandIconClick()
            }
            if(this.tree.checkOnClickNode&&!this.node.disabled)
            {
                this.handleCheckChange(null,{
                    target:{checked:!this.node.checked}
                })
            }
            this.tree.$emit('node-click',this.node.data,this.node,this)
        },
        handleContextMenu(event)
        {
            if(this.tree._events['node-contextmenu']&&this.tree._events['node-contextmenu'].length>0)
            {
                event.stopPropagation()
                event.preventDefault()
            }
            this.tree.$emit('node-contextmenu',event,this.node.data,this.node,this)
        },
        handleExpandIconClick(){
            if(this.node.isLeaf)return
            if(this.expanded)
            {
                this.tree.$emit('node-collapse',this.node.data,this.node,this)
                this.node.collapse()
            }else{
                this.node.expand()
                this.$emit('node-expand',this.node.data,this.node,this)
            }
        },
        handleCheckChange(value,ev)
        {
            this.node.setChecked(ev.target.checked,!this.tree.checkStrictly)
            this.$nextTick(()=>{
                const store = this.tree.store
                this.tree.$emit('check',this.node.data,{
                    checkedNodes:store.getCheckedNodes(),
                    checkedKeys:store.getCheckedKeys(),
                    halfCheckedNodes:store.getHalfCheckedNodes(),
                    halfCheckedKeys:store.getHalfCheckedKeys()
                })
            })
        },
        handleChildNodeExpand(nodeData,node,instance)
        {
            this.broadcast('LkTreeNode','tree-node-expand',node)
            this.tree.$emit('node-expand',nodeData,node,instance)
        },
        handleDragStart(event)
        {
            if(!this.tree.draggable) return
            this.tree.$emit('tree-node-drag-start',event,this)
        },
        handleDragOver(event)
       {
           if(!this.tree.draggable)return
           this.tree.$emit('tree-node-drag-over',event,this)
           event.preventDefault()
       },
       handleDrop(event){
           event.preventDefault()
       },
       handleDragEnd(event){
           if(!this.tree.draggable) return
           this.tree.$emit('tree-node-drag-end',event,this)
       }
    },
       created(){
           const parent= this.$parent
           if(parent.isTree)
           {
               this.tree=parent
           }else{
               this.tree=parent.tree
           }
           const tree=this.tree
           if(!tree){
               console.warn('Can not find node\'s tree.')
           }
           const props = tree.props||{}
           const childrenKey=props['children']||'children'
           this.$watch(`node.data.${childrenKey}`,()=>{
               this.node.updateChildren()
           })
           if(this.node.expanded)
           {
               this.expanded=true
               this.childNodeRendered=true
           }
           if(this.tree.accordion){
               this.$on('tree-node-expand',node=>{
                   if(this.node!==node)
                   {
                       this.node.collapse()
                   }
               })
           }
       }
}
</script>